package com.github.zyflzz.mycalculator;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.github.zyflzz.mycalculator.core.Calculator;
import com.github.zyflzz.mycalculator.core.Operation;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Stack;

@RequiresApi(api = Build.VERSION_CODES.O)
public class MainActivity extends AppCompatActivity {

    private Button seeHistory;
    private TextView bufferView;
    private TextView currentView;

    private Button button_2nd;
    private Button button_deg;
    private Button button_sin;
    private Button button_cos;
    private Button button_tan;
    private Button button_pow;
    private Button button_lg;
    private Button button_ln;
    private Button button_l_bracket;
    private Button button_r_bracket;
    private Button button_sqrt;
    private Button button_ac;
    private Button button_del;
    private Button button_percent;
    private Button button_div;
    private Button button_factorial;
    private Button button_times;
    private Button button_reciprocal;
    private Button button_minus;
    private Button button_pi;
    private Button button_plus;
    private Button button_sci;
    private Button button_e;
    private Button button_dot;
    private Button button_equals;

    private Button button_0;
    private Button button_1;
    private Button button_2;
    private Button button_3;
    private Button button_4;
    private Button button_5;
    private Button button_6;
    private Button button_7;
    private Button button_8;
    private Button button_9;

    private Stack<Boolean> lastIsNum = new Stack<>();
    private Stack<String> lastString = new Stack<>();

    private final Calculator calculator = Calculator.getCalculator();

    private final static String logtag = "RUN MAIN INFO";

    /**
     * 是否是第二模式
     */
    private boolean is_2nd = false;

    /**
     * 是否计算完成
     */
    private boolean is_calc_ok = false;

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Log.i(logtag, "START APP");

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initLayout();
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void initLayout() {
        Log.i(logtag, "Start Getting View");

        seeHistory = findViewById(R.id.seeHistory);
        bufferView = findViewById(R.id.bufferView);
        currentView = findViewById(R.id.currentView);

        button_0 = findViewById(R.id._0);
        button_1 = findViewById(R.id._1);
        button_2 = findViewById(R.id._2);
        button_3 = findViewById(R.id._3);
        button_4 = findViewById(R.id._4);
        button_5 = findViewById(R.id._5);
        button_6 = findViewById(R.id._6);
        button_7 = findViewById(R.id._7);
        button_8 = findViewById(R.id._8);
        button_9 = findViewById(R.id._9);
        button_2nd = findViewById(R.id._2nd);
        button_deg = findViewById(R.id._deg);
        button_sin = findViewById(R.id._sin);
        button_cos = findViewById(R.id._cos);
        button_tan = findViewById(R.id._tan);
        button_pow = findViewById(R.id._pow_x_y);
        button_lg = findViewById(R.id._lg);
        button_ln = findViewById(R.id._ln);
        button_l_bracket = findViewById(R.id._l_bracket);
        button_r_bracket = findViewById(R.id._r_bracket);
        button_sqrt = findViewById(R.id._sqrt_x);
        button_ac = findViewById(R.id._AC);
        button_del = findViewById(R.id._del);
        button_percent = findViewById(R.id._percent);
        button_div = findViewById(R.id._div);
        button_factorial = findViewById(R.id._factorial);
        button_times = findViewById(R.id._times);
        button_reciprocal = findViewById(R.id._reciprocal);
        button_minus = findViewById(R.id._minus);
        button_pi = findViewById(R.id._pi);
        button_plus = findViewById(R.id._plus);
        button_sci = findViewById(R.id._sci);
        button_e = findViewById(R.id._e);
        button_dot = findViewById(R.id._dot);
        button_equals = findViewById(R.id._equals);

        currentView.setText("");

        listenControlButton();
        listenNumberButton();
        listenOperationButton();
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void listenControlButton() {
        Log.i(logtag, "Start Set Control-Button Listener");
        button_ac.setOnClickListener(view -> ac());
        button_del.setOnClickListener(view -> del());
        button_dot.setOnClickListener(view -> dot());
        button_equals.setOnClickListener(view -> equals());
        button_2nd.setOnClickListener(view -> nd2());
        button_sci.setOnClickListener(view -> sci());
        seeHistory.setOnClickListener(view -> {
            Intent intent = new Intent();
            intent.setClass(MainActivity.this, HistoryActivity.class);
            startActivity(intent);
        });
    }

    private void listenOperationButton() {
        Log.i(logtag, "Start Set Operation-Button Listener");
        button_plus.setOnClickListener(view -> addOpToTextView(Operation.ADD.getText()));
        button_minus.setOnClickListener(view -> addOpToTextView(Operation.MINUS.getText()));
        button_times.setOnClickListener(view -> addOpToTextView(Operation.TIMES.getText()));
        button_div.setOnClickListener(view -> addOpToTextView(Operation.DIV.getText()));
        button_l_bracket.setOnClickListener(view -> addOpToTextView(Operation.LB.getText()));
        button_r_bracket.setOnClickListener(view -> addOpToTextView(Operation.RB.getText()));
        button_percent.setOnClickListener(view -> addOpToTextView(Operation.PERC.getText()));
        button_e.setOnClickListener(view -> addOpToTextView(Operation.E.getText()));
        button_sin.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.ASIN.getText() : Operation.SIN.getText()));
        button_cos.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.ACOS.getText() : Operation.COS.getText()));
        button_tan.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.ATAN.getText() : Operation.TAN.getText()));
        button_pow.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.SINH.getText() : Operation.POW.getText()));
        button_lg.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.COSH.getText() : Operation.LG.getText()));
        button_ln.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.TANH.getText() : Operation.LN.getText()));
        button_sqrt.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.SQUARE.getText() : Operation.SQRT.getText()));
        button_pi.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.EM.getText() : Operation.PI.getText()));
        button_deg.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.EXP.getText() : Operation.DEG.getText()));
        button_factorial.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.GAMMA.getText() : Operation.FRAC.getText()));
        button_reciprocal.setOnClickListener(view -> addOpToTextView(is_2nd ? Operation.CATALAN.getText() : Operation.RECI.getText()));
    }

    private void listenNumberButton() {
        Log.i(logtag, "Start Set Number-Button Listener");
        button_0.setOnClickListener(view -> addNumToTextView("0"));
        button_1.setOnClickListener(view -> addNumToTextView("1"));
        button_2.setOnClickListener(view -> addNumToTextView("2"));
        button_3.setOnClickListener(view -> addNumToTextView("3"));
        button_4.setOnClickListener(view -> addNumToTextView("4"));
        button_5.setOnClickListener(view -> addNumToTextView("5"));
        button_6.setOnClickListener(view -> addNumToTextView("6"));
        button_7.setOnClickListener(view -> addNumToTextView("7"));
        button_8.setOnClickListener(view -> addNumToTextView("8"));
        button_9.setOnClickListener(view -> addNumToTextView("9"));
    }

    private void addOpToTextView(String s) {
        if (is_calc_ok) {
            ac();
        }
        String text = String.valueOf(currentView.getText());
        if (!lastIsNum.empty() && lastIsNum.peek()) text = text + " " + s;
        else text = text + s;
        changeCurViewTextSize(text);
        currentView.setText(text);
        lastString.push(text);
        lastIsNum.push(false);
        is_calc_ok = false;
        Log.i(logtag, text);
    }

    private void addNumToTextView(String s) {
        if (is_calc_ok) {
            ac();
        }
        String text = String.valueOf(currentView.getText());
        text = text + s;
        changeCurViewTextSize(text);
        currentView.setText(text);
        lastString.push(text);
        lastIsNum.push(true);
        is_calc_ok = false;
        Log.i(logtag, text);
    }

    private void ac() {
        currentView.setText("");
        lastString.clear();
        lastIsNum.clear();
        is_calc_ok = false;
        Log.i(logtag, "ac");
    }

    private void del() {
        if (!lastString.empty() && !lastIsNum.empty()) {
            lastString.pop();
            lastIsNum.pop();
            String text = lastString.peek();
            changeCurViewTextSize(text);
            currentView.setText(text);
            is_calc_ok = false;
            Log.i(logtag, "del");
        }
    }

    private void dot() {
        if (lastIsNum.peek()) {
            String text = String.valueOf(currentView.getText());
            text = text + ".";
            changeCurViewTextSize(text);
            currentView.setText(text);
            lastString.push(text);
            is_calc_ok = false;
            Log.i(logtag, text);
        }
    }

    private Integer wrongCount = 0;
    private LocalDateTime flushTime = LocalDateTime.now();

    private void flushTime() {
        LocalDateTime now = LocalDateTime.now();
        Duration duration = Duration.between(flushTime, now);
        long hour = duration.toHours();
        if (hour > 0.5) {
            wrongCount = 0;
            flushTime = now;
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void equals() {
        flushTime();
        if (!lastString.empty()) {
            String input = lastString.peek();
            changeBufViewTextSize(input);
            String result;
            try {
                result = calculator.calc(input);
                changeCurViewTextSize(result);
                currentView.setText(result);
                bufferView.setText(input);
                Log.i(logtag, "result = " + result);
            } catch (Exception e) {
                calculator.clean();
                currentView.setText("");
                bufferView.setText("");
                wrongCount++;
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                if (wrongCount < 3) {
                    builder.setTitle("呀！出错了呢！");
                    builder.setMessage("一定是你不小心写错了吧，没关系 ~ 快检查一下 ~");
                } else if (wrongCount < 5) {
                    builder.setTitle("em mmmm，还是出错了呢！");
                    builder.setMessage("你要细心哦，不能总是犯错误的 ~");
                } else if (wrongCount < 7) {
                    builder.setTitle("还是错了哦！");
                    builder.setMessage("都说了语法有问题了，小朋友不能不听话哦！");
                } else if (wrongCount < 9) {
                    builder.setTitle("诶呀！");
                    builder.setMessage("诶呀！拜托检查一下语法好不好！为什么要“在酒吧里面点炒饭”呢？？？");
                } else if (wrongCount < 11) {
                    builder.setTitle("啊！气死啦！");
                    builder.setMessage("又错啦！你是故意的还是不小心？");
                } else if (wrongCount < 13) {
                    builder.setTitle("错啦！错啦！");
                    builder.setMessage("我觉得你不对劲，再警告你一次，不能随便输入哦！");
                } else if (wrongCount < 15) {
                    builder.setTitle("真是绝了！");
                    builder.setMessage("你 ** 的还真是个人才！");
                } else if (wrongCount < 17) {
                    builder.setTitle("不理你了！");
                    builder.setMessage("我觉得你是故意的，再警告你最后一次，我的耐心是有限的！");
                } else if (wrongCount < 19) {
                    builder.setTitle("***");
                    builder.setMessage("你**找茬是不是？？？");
                } else if (wrongCount < 21) {
                    builder.setTitle("你完蛋了！");
                    builder.setMessage("(╯‵□′)╯炸弹！•••*～●");
                } else if (wrongCount < 23) {
                    builder.setTitle("告诉你别找茬！");
                    builder.setMessage("你已经调戏我" + wrongCount + "次了！");
                } else if (wrongCount < 25) {
                    builder.setTitle("你已经调戏我" + wrongCount + "次了！");
                    builder.setMessage("信不信我打你哦！");
                } else if (wrongCount < 28) {
                    builder.setTitle("你是坏人！");
                    builder.setMessage("再错" + (28 - wrongCount) + "次我就走了！");
                } else {
                    wrongCount = 0;
                    flushTime = LocalDateTime.now();
                    finish();
                    android.os.Process.killProcess(android.os.Process.myPid());
                    System.exit(0);
                }

                builder.setPositiveButton("对不起我错了 ~", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Toast.makeText(MainActivity.this, "下次不允许了哦", Toast.LENGTH_SHORT).show();
                    }
                });
                AlertDialog dialog = builder.create();
                dialog.show();
            } finally {
                lastString.clear();
                lastIsNum.clear();
                is_calc_ok = true;
            }
        }
    }

    private void sci() {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("功能未开发");
        builder.setMessage("哇！你居然点击了这个，我都不知道这个按钮的作用是什么耶！快告诉我这个按钮是什么意思，好吗好吗？");
        builder.setPositiveButton("好的呢", (dialogInterface, i) -> Toast.makeText(MainActivity.this, "谢谢！", Toast.LENGTH_SHORT).show());
        builder.setNegativeButton("我也不知道呢", (dialogInterface, i) -> Toast.makeText(MainActivity.this, "没关系哒 ~", Toast.LENGTH_SHORT).show());
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    private void nd2() {
        if (is_2nd) {
            is_2nd = false;
            button_sin.setText(R.string._sin);
            button_cos.setText(R.string._cos);
            button_tan.setText(R.string._tan);
            button_deg.setText(R.string._deg);
            button_pow.setText(R.string._pow_x_y);
            button_lg.setText(R.string._lg);
            button_ln.setText(R.string._ln);
            button_sqrt.setText(R.string._sqrt_x);
            button_factorial.setText(R.string._factorial);
            button_reciprocal.setText(R.string._reciprocal);
            button_pi.setText(R.string._pi);
        } else {
            is_2nd = true;
            button_sin.setText(Operation.ASIN.getSymbol());
            button_cos.setText(Operation.ACOS.getSymbol());
            button_tan.setText(Operation.ATAN.getSymbol());
            button_deg.setText(Operation.EXP.getSymbol());
            button_pow.setText(Operation.SINH.getSymbol());
            button_lg.setText(Operation.COSH.getSymbol());
            button_ln.setText(Operation.TANH.getSymbol());
            button_sqrt.setText(Operation.SQUARE.getSymbol());
            button_factorial.setText(Operation.GAMMA.getSymbol());
            button_reciprocal.setText(Operation.CATALAN.getSymbol());
            button_pi.setText(Operation.EM.getSymbol());
        }
    }

    @SuppressLint("SetTextI18n")
    private void changeCurViewTextSize(@NonNull String text) {
        int size = text.length();
        Log.i(logtag, "changeCurViewTextSize, size = " + size);
        if (size < 10) {
            currentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 36);
        } else if (size < 30) {
            currentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
        } else {
            currentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 9);
        }
    }

    @SuppressLint("SetTextI18n")
    private void changeBufViewTextSize(@NonNull String text) {
        int size = text.length();
        Log.i(logtag, "changeCurViewTextSize, size = " + size);
        if (size < 10) {
            currentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
        } else if (size < 30) {
            currentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 12);
        } else {
            currentView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 9);
        }
    }
}